﻿//(c) Copyright [2015] Hewlett-Packard Enterprise Development, L.P.
//All rights reserved.
//Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
//1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
//2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
//THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 
//BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
//OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

using HP.HPTRIM.SDK;
using System;
using System.IO;

namespace HP.HPTRIM.Samples.Thumbnails
{
    /// <summary>
    /// Get the path to the electronic document for a Record or Rendition.  If document caching is enbled will return path to
    /// cached document. otherwise extract to TEMP and delete file on Dispose.
    /// If string constructor used will ensure file is deleted on Dispose.
    /// </summary>
    public class TempFile : IDisposable
    {
        private bool _deleteFile;

        public TempFile()
        {
            
        }
        public TempFile(ITrimDocument record)
        {
            FilePath = getFilePath(record);

        }

        public TempFile(string filePath)
        {

            _deleteFile = true;
            FilePath = filePath;

        }

        public string FilePath { get; set; }

        public bool FileExists
        {
            get
            {
                if (!string.IsNullOrWhiteSpace(FilePath))
                {
                    return File.Exists(FilePath);
                }
                return false;
            }
        }

        private string getFilePath(ITrimDocument record)
        {
            if (record == null)
            {
                throw new ApplicationException("Trim object not found.");
            }
            if (!record.IsDocumentInClientCache)
            {
                record.LoadDocumentIntoClientCache();
            }
            if (!string.IsNullOrEmpty(record.DocumentPathInClientCache))
            {
                return record.DocumentPathInClientCache;
            }

            _deleteFile = true;

            if (record is Record)
            {
                return (record as Record).GetDocument(Path.Combine(Path.GetTempPath(), (record as Record).SuggestedFileName), false, null, null);
            }

            if (record is RecordRendition)
            {
                ExtractDocument extractDoc = (record as RecordRendition).GetExtractDocument();
                extractDoc.DoExtract(Path.GetTempPath(), true, false, null);
                return extractDoc.FileName;
            }

            throw new ApplicationException(string.Format("{0} not supported", record.GetType().Name));

        }


        // This method accepts a string the representing the file with which to
        // compare. A return value of 0 indicates that the contents of the files
        // are the same. A return value of any other value indicates that the 
        // files are not the same.
        // thanks to MS support I did not have to write code to loop through two files myself:
        // https://support.microsoft.com/en-us/kb/320348
        public bool CompareWith(string file)
        {
            int file1byte;
            int file2byte;
            FileStream fs1;
            FileStream fs2;

            // Determine if the same file was referenced two times.
            if (FilePath == file)
            {
                // Return true to indicate that the files are the same.
                return true;
            }

            // Open the two files.
            fs1 = File.OpenRead(FilePath);
            fs2 = File.OpenRead(file);

            // Check the file sizes. If they are not the same, the files 
            // are not the same.
            if (fs1.Length != fs2.Length)
            {
                // Close the file
                fs1.Close();
                fs2.Close();

                // Return false to indicate files are different
                return false;
            }

            // Read and compare a byte from each file until either a
            // non-matching set of bytes is found or until the end of
            // file1 is reached.
            do
            {
                // Read one byte from each file.
                file1byte = fs1.ReadByte();
                file2byte = fs2.ReadByte();
            }
            while ((file1byte == file2byte) && (file1byte != -1));

            // Close the files.
            fs1.Close();
            fs2.Close();

            // Return the success of the comparison. "file1byte" is 
            // equal to "file2byte" at this point only if the files are 
            // the same.
            return ((file1byte - file2byte) == 0);
        }


        public void Dispose()
        {
            if (_deleteFile)
            {
                File.Delete(FilePath);
            }
        }
    }
}
